package ods_config

import (
	"fmt"
	"server/apps/ods/ods_field"
	"server/apps/ods/ods_job"
	"server/apps/ods/ods_map"
	"server/apps/ods/ods_odb"
	"server/apps/ods/ods_table"
	"server/dbtools/xmysql"
	"server/global"
	"server/model/common/request"
	"server/model/common/response"

	"server/utils"
	"strings"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"

	"server/dbtools/xoracle"
)

type OdsDbConfigApi struct {
}

var odsDbConfigService = OdsDbConfigService{}

func (odsDbConfigApi *OdsDbConfigApi) CreateOdsDbConfig(c *gin.Context) {
	var odsDbConfig OdsDbConfig
	err := c.ShouldBindJSON(&odsDbConfig)
	if err != nil {
		global.Logger.Info("前端传回ods配置获取失败！")
		response.FailWithMessage(err.Error(), c)
		return
	}

	var odsTb = odsDbConfig.OdsDbTb
	var odsFlds = odsDbConfig.OdsDbFlds

	totalFlds := len(odsFlds)
	successCount := 0
	ignoreCount := 0

	if odsTb.SrcDbId == 0 || odsTb.SrcSchemaName == "" || odsTb.SrcTbName == "" {
		msg := "srcDbId、SrcSchemaName、SrcTbName不存在！"
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}
	if odsTb.ID > 0 {
		msg := "Ods表已经存在！"
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}
	if len(odsFlds) == 0 {
		msg := "odb表字段不存在"
		global.Logger.Warn(msg)
		response.FailWithMessage(msg, c)
		return
	}
	var colsString string
	for i, oneFld := range odsFlds {
		colsString += oneFld.ColName
		if i < len(odsFlds)-1 {
			colsString += ","
		}
	}
	odsTb.ColsString = colsString
	odsTb.OdsDbType = global.XidwConfig.OdsDB.DbType
	odsTb.OdsTbName = odsTb.Bsm
	odsTb.SrcDataType = "ODB"
	err = odsTb.SetInit()
	if err != nil {
		msg := "odsTbId初始化失败"
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	var tb ods_table.OdsDbTable
	if err = global.SysDB.Where("bsm =?", odsTb.Bsm).First(&tb).Error; err == nil {
		if err = global.SysDB.Unscoped().Delete(ods_table.OdsDbTable{}, "bsm=?", odsTb.Bsm).Error; err != nil {
			global.Logger.Error("删除OdsTb失败!", zap.Error(err))
			msg := fmt.Sprintf("OdsDbTb %s 删除 err:%s", odsDbConfig.OdsDbTb.OdsTbName, err)
			response.FailWithMessage(msg, c)
			return
		}
	}
	if err = (&odsTb).Create(); err != nil {
		msg := "创建odsTb失败"
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	srcDbType := odsTb.SrcDbType
	tgtDbType := global.XidwConfig.OdsDB.DbType
	dbFldMap, err := ods_map.GetDbMap(srcDbType, tgtDbType)
	var sqlCreateTb = fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n", odsTb.OdsTbName)
	var strColKey string
	for idx, oneFld := range odsFlds {
		oneFld.OdbId = odsTb.SrcDbId
		oneFld.OdbSchema = odsTb.SrcSchemaName
		oneFld.OdbTbName = odsTb.SrcTbName
		oneFld.OdsTbId = odsTb.ID
		oneFld.OdsTbName = odsTb.Bsm
		err = oneFld.SetBsm()
		if err != nil {
			response.FailWithMessage(fmt.Sprintf("odsFld设置标识码失败:%s", err), c)
			return
		}
		if oneFld.Bsm == "" {
			response.FailWithMessage(fmt.Sprintf("odsFld标识码为空"), c)
			return
		}

		oneFld.OdsColName = oneFld.ColName
		oneFld.OdsColComment = oneFld.ColComment
		oneFld.OdsCharSet = oneFld.CharSet
		fmt.Printf("oneFld.ColType:(%s),oneFld.DataType:(%s), oneFld.DataLength:%d\n", oneFld.ColType, oneFld.DataType, oneFld.DataLength)
		if oneFld.DataLength > 0 {
			oneFld.OdsDataLength = oneFld.DataLength
		} else {
			dLen, err := utils.FindDataLen(oneFld.ColType)
			if err != nil {
				oneFld.OdsDataLength = 0
			} else {
				oneFld.OdsDataLength = dLen
			}
		}

		if oneFld.DataType != "" {
			oneFld.OdsDataType = dbFldMap[strings.ToLower(oneFld.DataType)]
		} else {
			oneFld.ColDataType = utils.FindDataType(strings.ToLower(oneFld.ColType))
			oneFld.OdsDataType = dbFldMap[oneFld.ColDataType]
		}

		if oneFld.OdsDataType == "" {
			oneFld.ColConv = "失败"
			oneFld.OdsDataType = "varchar"
			if oneFld.DataLength == 0 {
				oneFld.OdsDataLength = 120
			}
		} else {
			oneFld.ColConv = "成功"
		}

		if oneFld.OdsDataType == "datetime" {
			oneFld.OdsDataLength = 6
		}
		if oneFld.ColType != "" {
			oneFld.OdsColType = oneFld.ColType
		} else {
			if oneFld.DataLength > 0 {
				oneFld.OdsColType = fmt.Sprintf("%s(%d)", oneFld.OdsDataType, oneFld.OdsDataLength)
			} else {
				oneFld.OdsColType = oneFld.OdsDataType
			}
		}
		if (oneFld.OdsDataType == "varchar" || oneFld.OdsDataType == "nvarchar") && oneFld.OdsDataLength > 1000 {
			oneFld.OdsColType = "text"
		}

		sqlCreateTb += fmt.Sprintf("`%s` %s", oneFld.OdsColName, oneFld.OdsColType)
		if oneFld.CharSet != "" {
			sqlCreateTb += fmt.Sprintf(" CHARACTER SET %s", oneFld.OdsCharSet)
		}
		if oneFld.ColComment != "" {
			sqlCreateTb += fmt.Sprintf(" COMMENT '%s'", oneFld.OdsColComment)
		}
		if oneFld.ColKey == "PRI" {
			if strColKey == "" {
				strColKey += fmt.Sprintf("`%s`", oneFld.ColName)
			} else {
				strColKey += fmt.Sprintf(", `%s`", oneFld.ColName)
			}
		}
		if idx < (len(odsFlds) - 1) {
			sqlCreateTb += ",\n"
		}

		var fld ods_field.OdsDbField
		if err = global.SysDB.Where("bsm =?", oneFld.Bsm).First(&fld).Error; err == nil {
			if err = global.SysDB.Unscoped().Delete(ods_field.OdsDbField{}, "bsm=?", oneFld.Bsm).Error; err != nil {
				global.Logger.Error("删除OdsFld失败!", zap.Error(err))
				msg := fmt.Sprintf("OdsFld(%s)删除失败:%s", oneFld.Bsm, err)
				response.FailWithMessage(msg, c)
				return
			}
		}
		if err := (&oneFld).Create(); err != nil {
			msg := fmt.Sprintf("创建OdsFld失败:%v", err)
			response.FailWithMessage(msg, c)
			return
		}
	}

	var odsJob ods_job.OdsJob
	odsJob.OdsTbId = odsTb.ID
	odsJob.OdsTbName = odsTb.OdsTbName
	if odsJob.SyncColName == "" {
		odsJob.SyncColName = odsTb.PriCol
	}
	if odsJob.Step == 0 {
		odsJob.Step = 500
	}
	var job ods_job.OdsJob
	if err = global.SysDB.Where("odsTbId =? ", odsTb.ID).First(&job).Error; err == nil {
		if err = global.SysDB.Unscoped().Delete(ods_job.OdsJob{}, "odsDbTbId =? ", odsTb.ID).Error; err != nil {
			global.Logger.Error("删除OdsJob失败!", zap.Error(err))
			msg := fmt.Sprintf("OdsJob(%d)删除失败:%s", odsTb.ID, err)
			response.FailWithMessage(msg, c)
			return
		}
	}
	if err := (&odsJob).Create(); err != nil {
		msg := fmt.Sprintf("创建OdsJob失败:%v", err)
		response.FailWithMessage(msg, c)
		return
	}
	odsDbConfig.OdsDbJob = odsJob

	if strColKey != "" {
		sqlCreateTb += fmt.Sprintf(",\nPRIMARY KEY (%s)\n", strColKey)
	}
	odsDb := global.OdsDB
	if odsDb == nil {
		msg := fmt.Sprintf("ods数据库连接失败")
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}
	sqlDropTable := fmt.Sprintf("DROP TABLE IF EXISTS %s;", odsTb.OdsTbName)
	_, err = odsDb.Exec(sqlDropTable)
	if err != nil {
		msg := fmt.Sprintf("删除ODS表失败,err:%s\n,sql:%s", err.Error(), sqlDropTable)
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	sqlCreateTb += fmt.Sprintf(") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '%s' ROW_FORMAT = DYNAMIC;", odsTb.OdsTbComment)
	_, err1 := odsDb.Exec(sqlCreateTb)
	if err1 != nil {
		msg := fmt.Sprintf("创建ODS表失败：%s", err1.Error())
		global.Logger.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	backMsg := fmt.Sprintf("处理%d条，成功%d条,因重复忽略%d条", totalFlds, successCount, ignoreCount)

	var subKey = []string{"ColName", "DataType", "DataLength", "ColType", "ColComment", "ColKey", "ExampleData"}
	var subVel = []string{"列名", "数据类型", "数据长度", "列类型", "列注释", "是否主键", "数据示例"}
	var fldsData = make([]map[string]interface{}, len(subKey))
	for s := 0; s < len(subKey); s++ {
		var one = make(map[string]interface{})
		one["l0"] = subVel[s]
		for l := 0; l < len(odsFlds); l++ {
			v, err := utils.GetStructStringField(odsFlds[l], subKey[s])
			if err != nil {
				v = ""
			}
			key := fmt.Sprintf("l%d", l+1)
			one[key] = v
		}
		fldsData[s] = one
	}

	response.OkWithDetailed(gin.H{
		"odsDbTb": odsTb,
		"odsDbFlds": odsFlds,
		"odsDbJob": odsJob,
		"fldsData": fldsData,
	}, backMsg, c)
}

func (odsDbConfigApi *OdsDbConfigApi) DeleteOdsDbConfig(c *gin.Context) {
	var odsDbConfig OdsDbConfig
	err := c.ShouldBindJSON(&odsDbConfig)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	var errMsg string

	err = global.SysDB.Unscoped().Delete(ods_job.OdsJob{}, "odsTbName=?", odsDbConfig.OdsDbJob.OdsTbName).Error
	if err != nil {
		global.Logger.Error("删除失败!", zap.Error(err))
		errMsg += fmt.Sprintf("OdsDbJob %s 删除 err:%s", odsDbConfig.OdsDbJob.OdsTbName, err)
	}

	for _, oneFld := range odsDbConfig.OdsDbFlds {
		err = global.SysDB.Unscoped().Delete(ods_field.OdsDbField{}, "odsTbName=?", odsDbConfig.OdsDbTb.OdsTbName).Error
		if err != nil {
			global.Logger.Error("删除失败!", zap.Error(err))
			errMsg += fmt.Sprintf("OdsDbFlds %d 删除 err:%s", oneFld.ID, err)
		}
	}

	err = global.SysDB.Unscoped().Delete(ods_table.OdsDbTable{}, "odsTbName=?", odsDbConfig.OdsDbTb.OdsTbName).Error
	if err != nil {
		global.Logger.Error("删除失败!", zap.Error(err))
		errMsg += fmt.Sprintf("OdsDbTb %s 删除 err:%s", odsDbConfig.OdsDbTb.OdsTbName, err)
	}


	if errMsg != "" {
		response.FailWithMessage(errMsg, c)
	} else {
		response.OkWithMessage("删除成功", c)
	}
}

func (odsDbConfigApi *OdsDbConfigApi) DeleteOdsDbConfigByIds(c *gin.Context) {
	var IDS request.IdsReq
	err := c.ShouldBindJSON(&IDS)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	deletedBy := utils.GetUserID(c)
	if err := odsDbConfigService.DeleteOdsDbConfigByIds(IDS, deletedBy); err != nil {
		global.Logger.Error("批量删除失败!", zap.Error(err))
		response.FailWithMessage("批量删除失败", c)
	} else {
		response.OkWithMessage("批量删除成功", c)
	}
}

func (odsDbConfigApi *OdsDbConfigApi) UpdateOdsDbConfig(c *gin.Context) {
	var odsDbConfig OdsDbConfig
	err := c.ShouldBindJSON(&odsDbConfig)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := odsDbConfigService.UpdateOdsDbConfig(odsDbConfig); err != nil {
		global.Logger.Error("更新失败!", zap.Error(err))
		response.FailWithMessage("更新失败", c)
	} else {
		response.OkWithMessage("更新成功", c)
	}
}

func (odsDbConfigApi *OdsDbConfigApi) FindOdsDbConfig(c *gin.Context) {
	var odsDbConfig OdsDbConfig
	err := c.ShouldBindQuery(&odsDbConfig)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.FailWithMessage("查询失败", c)
}

func (odsDbConfigApi *OdsDbConfigApi) GetOdsDbConfigList(c *gin.Context) {
	var pageInfo OdsDbConfigSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if list, total, err := odsDbConfigService.GetOdsDbConfigInfoList(pageInfo); err != nil {
		global.Logger.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	}
}

func (odsDbConfigApi *OdsDbConfigApi) GetAllOdsDbConfigs(c *gin.Context) {
	odsDbConfig, err := odsDbConfigService.GetAllOdsDbConfigs()
	if err != nil {
		global.Logger.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(gin.H{"odsDbConfig": odsDbConfig}, "获取成功", c)
	}
}

func (odsDbConfigApi *OdsDbConfigApi) GetOdsDbConfig(c *gin.Context) {
	var odsDbConfig OdsDbConfig

	var errMsg string

	err := c.BindJSON(&odsDbConfig)
	if err != nil {
		errMsg = "获取前端odsTb数据失败:"
		global.Logger.Info(errMsg)
		global.Logger.Error(errMsg, zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}
	var odsDbTb ods_table.OdsDbTable
	var odsDbFlds []ods_field.OdsDbField
	var odsJob ods_job.OdsJob

	err = odsDbConfig.OdsDbTb.SetBsm()
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	println("标识码：", odsDbTb.Bsm)
	var tbCount int64
	global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", odsDbConfig.OdsDbTb.Bsm).Count(&tbCount)

	if tbCount > 0 {
		global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", odsDbConfig.OdsDbTb.Bsm).First(&odsDbTb)
		global.SysDB.Find(&[]ods_field.OdsDbField{}, "odsTbId = ?", odsDbTb.ID).Find(&odsDbFlds)
		global.SysDB.Find(&[]ods_job.OdsJob{}, "odsTbId = ?", odsDbTb.ID).First(&odsJob)
		if odsJob.OdsTbId == odsDbTb.ID {
			odsJob.InOdsTb = 1
		}
		odsJob.CheckInTimer()
	}

	if tbCount == 0 {
		odsDbTb = odsDbConfig.OdsDbTb
		odsDbTb.ID = 0

		priKey, uniKey, err := odsDbTb.GetPriUniKey()
		if err != nil {
			errMsg = fmt.Sprintf("\n获取主键失败:%s", err)
			global.Logger.Error(errMsg, zap.Error(err))
			response.FailWithMessage(errMsg, c)
		}
		odsDbTb.PriCol = priKey
		odsDbTb.UniCol = uniKey
		odsDbTb.OdsSchemaName = global.XidwConfig.OdsDB.Dbname
		odsDbTb.OdsTbLabel = odsDbTb.Bsm

		odsDbFlds, err = odsDbTb.GetOdbFlds()
		if err != nil {
			errMsg = fmt.Sprintf("\n获取Flds数据失败:%s", err)
			global.Logger.Error(errMsg, zap.Error(err))
			response.FailWithMessage(errMsg, c)
		}
		var exampleData map[string]string
		exampleData, err = odsDbTb.GetSrcDataOne()
		if err != nil {
			errMsg = fmt.Sprintf("\n获取示例数据失败:%v", err)
			global.Logger.Error(errMsg, zap.Error(err))
		}
		if len(odsDbFlds) > 0 && len(exampleData) > 0 && len(odsDbFlds) == len(exampleData) {
			for idx := range odsDbFlds {
				if len(exampleData[odsDbFlds[idx].ColName]) > 200 {
					exampleData[odsDbFlds[idx].ColName] = exampleData[odsDbFlds[idx].ColName][0:198]
				}
				odsDbFlds[idx].ExampleData = exampleData[odsDbFlds[idx].ColName]
			}
		}
	}
	var subKey = []string{"ColName", "DataType", "DataLength", "ColType", "ColComment", "ColKey", "ExampleData"}
	var subVel = []string{"列名", "数据类型", "数据长度", "列类型", "列注释", "是否主键", "数据示例"}
	var fldsData = make([]map[string]interface{}, len(subKey))
	for s := 0; s < len(subKey); s++ {
		var one = make(map[string]interface{})
		one["l0"] = subVel[s]
		for l := 0; l < len(odsDbFlds); l++ {
			v, err := utils.GetStructStringField(odsDbFlds[l], subKey[s])
			if err != nil {
				v = ""
			}
			key := fmt.Sprintf("l%d", l+1)
			one[key] = v
		}
		fldsData[s] = one
	}

	response.OkWithDetailed(gin.H{
		"odsDbTb": odsDbTb,
		"odsDbFlds": odsDbFlds,
		"odsDbJob": odsJob,
		"fldsData": fldsData,
	}, "获取成功", c)
}

func (odsDbConfigApi *OdsDbConfigApi) InitOdsDbConfig(c *gin.Context) {
	response.FailWithMessage("获取初始化数据失败", c)
}

type DbTree struct {
	Label          string            `json:"label"`
	Type           string            `json:"type"`
	OdsDb          ods_odb.OdsOdb    `json:"odsDb"`
	SchemaChildren []*SchemaChildren `json:"children"`
}

type SchemaChildren struct {
	Label string `json:"label"`
	Type  string `json:"type"`
	InOds int64  `json:"inOds"`
	TbChildren []TbChildren `json:"children"`
}

type TbChildren struct {
	Label string               `json:"label"`
	Type  string               `json:"type"`
	InOds int64                `json:"inOds"`
	OdsTb ods_table.OdsDbTable `json:"odsDbTb"`
}

func (odsDbConfigApi *OdsDbConfigApi) GetOdsDbTree(c *gin.Context) {
	dbTrees := make([]DbTree, 0)

	var odbServerList []ods_odb.OdsOdb

	err := global.SysDB.Find(&odbServerList).Error
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	for _, oneOdbServer := range odbServerList {
		if len(dbTrees) == 0 {
			var oneDbTree DbTree
			oneDbTree.Label = oneOdbServer.DbTopic
			oneDbTree.Type = "odsDb"
			oneDbTree.OdsDb = oneOdbServer
			dbTrees = append(dbTrees, oneDbTree)
		}

		switch oneOdbServer.DbType {
		case "mysql":
			OdbConn, err := oneOdbServer.GetConn()
			if err != nil {
				global.Logger.Error(fmt.Sprintf("获取ODB(%d)连接失败:", oneOdbServer.ID), zap.Error(err))
				continue
			}

			schemaList, err := xmysql.GetMysqlSchemaList(OdbConn)
			if err != nil {
				global.Logger.Error(fmt.Sprintf("查询ODB(%d)所有schema失败!", oneOdbServer.ID), zap.Error(err))
				continue
			}

			for _, oneSchemaName := range schemaList {

				tbNameList, err := xmysql.GetMysqlTbList(OdbConn, oneSchemaName)
				if err != nil {
					global.Logger.Error(fmt.Sprintf("查询ODB(%d)schema(%s)所有表失败!", oneOdbServer.ID, oneSchemaName), zap.Error(err))
					continue
				}

				if len(tbNameList) > 0 {
					for _, oneTbName := range tbNameList {

						var oneOdsTb ods_table.OdsDbTable
						oneOdsTb.SrcDbType = oneOdbServer.DbType
						oneOdsTb.SrcDbId = oneOdbServer.ID
						oneOdsTb.SrcSchemaName = oneSchemaName
						oneOdsTb.SrcTbName = oneTbName
						err = oneOdsTb.SetBsm()
						if err != nil {
							global.Logger.Error(err.Error(), zap.Error(err))
						}
						oneOdsTb.OdsTbName = oneOdsTb.Bsm
						var tbCount int64
						global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", oneOdsTb.Bsm).Count(&tbCount)
						if tbCount > 0 {
							global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", oneOdsTb.Bsm).First(&oneOdsTb)
							oneOdsTb.InOds = tbCount
						}

						var t TbChildren
						t.Label = oneTbName
						t.Type = "odsDbTb"
						t.InOds = tbCount
						t.OdsTb = oneOdsTb

						for j, r := range dbTrees {
							if r.Label == oneOdbServer.DbTopic {
								break
							} else if j == len(dbTrees)-1 {
								var oneDbTree DbTree
								oneDbTree.Label = oneOdbServer.DbTopic
								oneDbTree.Type = "odsDb"
								oneDbTree.OdsDb = oneOdbServer
								dbTrees = append(dbTrees, oneDbTree)
							}
						}
						for m, r := range dbTrees {
							if r.Label == oneOdbServer.DbTopic {
								var s SchemaChildren
								s.Label = oneSchemaName
								s.Type = "odsDbSchema"
								if len(r.SchemaChildren) == 0 {
									s.TbChildren = append(s.TbChildren, t)
									dbTrees[m].SchemaChildren = append(dbTrees[m].SchemaChildren, &s)
								} else {
									for n, c := range r.SchemaChildren {
										if c.Label == oneSchemaName {
											dbTrees[m].SchemaChildren[n].TbChildren = append(dbTrees[m].SchemaChildren[n].TbChildren, t)
											break
										} else if n == len(dbTrees[m].SchemaChildren)-1 {
											s.TbChildren = append(s.TbChildren, t)
											dbTrees[m].SchemaChildren = append(dbTrees[m].SchemaChildren, &s)
										}
									}
								}
							}
						}
					}
				}

			}
		case "oracle":
			fmt.Sprintln("源数据库:oracle")
			OdbConn, err := oneOdbServer.GetConn()
			if err != nil {
				msg := fmt.Sprintf("获取oracle 连接失败:%v", zap.Error(err))
				global.Logger.Error(msg)
				continue
			}

			fmt.Sprintln("获取oracle所有schema名称数组")
			schemaList, err := xoracle.GetOracleSchemaList(OdbConn)
			if err != nil {
				global.Logger.Error("查询oracle所有schema失败!", zap.Error(err))
				response.FailWithMessage("查询oracle所有schema失败!", c)
				continue
			}
			if len(schemaList) == 0 {
				break
			}
			for _, oneSchemaName := range schemaList {

				tbNameList, err := xoracle.GetOracleTbList(OdbConn, oneSchemaName)
				if err != nil {
					global.Logger.Error("查询mysql one schema下所有表失败!", zap.Error(err))
					response.FailWithMessage("查询mysql one schema下所有表失败", c)
					continue
				}

				if len(tbNameList) > 0 {
					for _, oneTbName := range tbNameList {
						var odsTbName string
						odsTbName = fmt.Sprintf("%d_%s_%s", oneOdbServer.ID, oneSchemaName, oneTbName)
						for j, r := range dbTrees {
							if r.Label == oneOdbServer.DbTopic {
								break
							} else if j == len(dbTrees)-1 {
								var oneDbTree DbTree
								oneDbTree.Label = oneOdbServer.DbTopic
								oneDbTree.Type = "odsDb"
								oneDbTree.OdsDb = oneOdbServer

								dbTrees = append(dbTrees, oneDbTree)
							}
						}
						var oneOdsTb ods_table.OdsDbTable
						oneOdsTb.SrcDbId = oneOdbServer.ID
						oneOdsTb.SrcSchemaName = oneSchemaName
						oneOdsTb.SrcTbName = oneTbName
						err = oneOdsTb.SetBsm()
						if err != nil {
							global.Logger.Error(err.Error(), zap.Error(err))
							response.FailWithMessage(err.Error(), c)
							return
						}

						var tbCount int64
						global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", oneOdsTb.Bsm).Count(&tbCount)
						if tbCount > 0 {
							global.SysDB.Find(&[]ods_table.OdsDbTable{}, "bsm =?", oneOdsTb.Bsm).First(&oneOdsTb)
							oneOdsTb.InOds = tbCount
						} else {
							oneOdsTb.SrcDbType = oneOdbServer.DbType
							oneOdsTb.SrcSchemaName = oneSchemaName
							oneOdsTb.SrcTbName = oneTbName
							oneOdsTb.OdsTbName = odsTbName
						}

						var t TbChildren
						t.Label = oneTbName
						t.Type = "odsDbTb"
						t.InOds = tbCount
						t.OdsTb = oneOdsTb

						for m, r := range dbTrees {
							if r.Label == oneOdbServer.DbTopic {
								var s SchemaChildren
								s.Label = oneSchemaName
								s.Type = "odsDbSchema"


								if len(r.SchemaChildren) == 0 {
									dbTrees[m].SchemaChildren = append(dbTrees[m].SchemaChildren, &s)
								} else {
									for n, c := range r.SchemaChildren {
										if c.Label == oneSchemaName {
											dbTrees[m].SchemaChildren[n].TbChildren = append(dbTrees[m].SchemaChildren[n].TbChildren, t)
										} else if n == len(dbTrees[m].SchemaChildren)-1 {
											s.TbChildren = append(s.TbChildren, t)
											dbTrees[m].SchemaChildren = append(dbTrees[m].SchemaChildren, &s)
										}
									}
								}
							}
						}
					}
				}

			}
		default:
			break
		}
	}
	response.OkWithData(gin.H{"odsDbTree": dbTrees}, c)
}

func (odsDbConfigApi *OdsDbConfigApi) StartOdsDbJob(c *gin.Context) {
	var odsDbJob ods_job.OdsJob
	var odsDbConfig OdsDbConfig
	var err error

	err = c.ShouldBindJSON(&odsDbJob)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	global.Logger.Info(fmt.Sprintf("启动数据同步任务,表%s,%s,%s：", odsDbJob.OdsTbName, odsDbJob.JobType, odsDbJob.SyncType))
	odsDbConfig, err = InitOdsDbConfig(odsDbJob.OdsTbId)
	if err != nil {
		msg := fmt.Sprintf(" 获取同步配置数据,失败:%v", err)
		response.FailWithMessage(msg, c)
		return
	}

	odsDbConfig.OdsDbJob.SetReady()
	if odsDbConfig.OdsDbJob.Ready == 0 {
		msg := fmt.Sprintf(" 配置数据不完整")
		response.FailWithMessage(msg, c)
		return
	}

	switch odsDbJob.JobType {
	case "同步一次":
		err = StartOnceJob(odsDbJob.ID)
	case "定时同步":
		err = StartTmJob(odsDbJob.ID)
	case "实时同步":
		err = StartRtJob(odsDbJob.ID)
	default:
		err = fmt.Errorf("启动任务失败,未知同步方式:%s", odsDbJob.SyncType)
	}
	if err != nil {
		msg := fmt.Sprintf("启动任务失败:%v", err)
		global.Logger.Error("启动任务失败!", zap.Error(err))
		response.FailWithMessage(msg, c)
		return
	}
	global.JobRunning[odsDbJob.OdsTbName] = 1
	keys := utils.MapKeys(global.JobRunning)
	response.OkWithDetailed(gin.H{"jobRunning": keys}, "启动任务成功", c)
}

func (odsDbConfigApi *OdsDbConfigApi) StopOdsDbJob(c *gin.Context) {
	var odsDbJob ods_job.OdsJob

	err := c.ShouldBindJSON(&odsDbJob)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	switch odsDbJob.JobType {
	case "同步一次":
		err = StopOnceJob(odsDbJob.ID)
	case "定时同步":
		err = StopTmJob(odsDbJob.ID)
	case "实时同步":
		err = StopRtJob(odsDbJob.ID)
	default:
		err = fmt.Errorf("停止任务失败,未知同步方式:%s", odsDbJob.SyncType)
	}
	if err != nil {
		msg := fmt.Sprintf("停止任务失败:%v", err)
		global.Logger.Error(msg, zap.Error(err))
		response.FailWithMessage(msg, c)
		return
	}
	response.OkWithMessage("停止数据同步任务成功", c)
}
